package frame.project;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import frame.project.AlbumCustom.ListenerLabelBtn;
import frame.project.AlbumCustom.ListenerLabelOk;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView.ScaleType;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.SlidingDrawer;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.SlidingDrawer.*;
import android.widget.Toast;

public class AlbumGrid extends Activity {
	// Collection of images' path + id in the database
	ArrayList<ArrayList<String>> imgUriList = new ArrayList<ArrayList<String>>();
	
	String colorIndex;
	Button btn, btnSetting;
	Dialog imgDialog;
	ImageView imgEnlarge, imgThumbs;
	GridView gridView;
	ViewPager pager;
	Bitmap bmEnlarge, bm;
	int pos;
	
	ImageProduce image = new ImageProduce();
	LoadImages LoadImages = new LoadImages();

	// Array list used to hold buttons for listeners' use
	ArrayList<Button> btnList = new ArrayList<Button>();
	
	ArrayList<LoadedImage> photos = new ArrayList<LoadedImage>();
	
	// Collection of colors name, for updating database
	String[] color = {"Red", "Orange", "Yellow", "Green", "Blue", "Pink", "Purple", "Neutral"};
	
	// Database access purpose
	DBAdapter db = new DBAdapter(this);
	
	// Array of button colors' IDs, used for listener
	int[] btnColor = {R.id.btnRed, R.id.btnOrange, R.id.btnYellow, R.id.btnGreen, R.id.btnBlue, R.id.btnPink, R.id.btnPurple, R.id.btnNeutral};
	
	ImageAdapter imageAdapter;

	ImagePager pagerAdapter;
	
	/**
	 * Adapter class for Grid View
	 * Displays pictures in GridView
	 * @author Marcel
	 *
	 */
    public class ImageAdapter extends BaseAdapter {
    	
    	private Context mContext;    	
    	public ImageAdapter(Context c) {
    		mContext = c;	
    	}
    	
    	void add(LoadedImage image){
    		photos.add(image);
    	}

		public int getCount() {
			return photos.size();
		}

		public Object getItem(int arg0) {
			return null;
		}

		public long getItemId(int position) {
			return 0;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			
			// if it's not recycled, initialize some attributes
	        if (convertView == null) {  
	            imgThumbs = new ImageView(mContext);
	            imgThumbs.setScaleType(ScaleType.CENTER_CROP);
	            imgThumbs.setLayoutParams(new GridView.LayoutParams(180, 180));
	            
	            //sets padding (distance between thumbnails
	            imgThumbs.setPadding(10, 5, 10, 5);
	        } else {
	            imgThumbs = (ImageView) convertView;
	        }

	        // Retrieves image from LoadedImage object and set it to the ImageView
	        imgThumbs.setImageBitmap(photos.get(position).getBitmap());
	        
	        imgThumbs.setOnClickListener(new ListenerImageClick(position));
	        imgThumbs.setOnLongClickListener(new ListenerImageLong(position));
	        
	        return imgThumbs;
		}
	}
        
    /**
     * Adapter class for ViewPager
     * Displays next and previous pictures by swiping right n left
     * @author Marcel
     *
     */
    public class ImagePager extends PagerAdapter{
		@Override
		public int getCount() {
			return imgUriList.size();
		}

		@Override
		public boolean isViewFromObject(View view, Object object) {
			return view == ((ImageView) object);
		}
		
		 @Override
		 // Displays picture
		 public Object instantiateItem(ViewGroup container, int position) {
			 Context context = AlbumGrid.this;
			 if (imgEnlarge != null){
				 imgEnlarge = null;
			 }
			 
		     imgEnlarge = new ImageView(context);
		     imgEnlarge.setScaleType(ImageView.ScaleType.FIT_CENTER);
		     imgEnlarge.setAdjustViewBounds(true);
		     
		     // Decode image using the path
		     bmEnlarge = image.decodeBitmap(imgUriList.get(position).get(0), 600 , 600);
		     
		     imgEnlarge.setImageBitmap(bmEnlarge);
		     imgEnlarge.setOnLongClickListener(new ListenerImageLong(position));
		     ((ViewPager) container).addView(imgEnlarge, 0);
		     
		     return imgEnlarge;
		 }

		 @Override
		    public void destroyItem(ViewGroup collection, int position, Object o) {
				Log.d("DESTROY", "destroying view at position " + position);
			    collection.removeView((View) o);
			    System.gc();
		    }
    }
    

    /**
     * Private class used to store Bitmap object after retrieved
     * @author Marcel
     */
    private static class LoadedImage {
        Bitmap mBitmap;

        LoadedImage(Bitmap bitmap) {
            mBitmap = bitmap;
        }

        public Bitmap getBitmap() {
            return mBitmap;
        }
    }
    
    /**
     * Load Images' path from database
     * Create bitmap image from the path and store to ArrayList<LoadedImage>
     * Tasks are done in background - so that the performance will be increased
     * User will not have to wait until loading process to be able to browse gallery
     * @author Marcel
     */
    public class LoadImages extends AsyncTask<Object, LoadedImage, String>{
    	@Override
	    protected void onPreExecute() {
	        super.onPreExecute();
	        //db.open();
	    }
    	
		@Override
		protected String doInBackground(Object... params) {
	        Cursor c = db.getPath();
	        c.moveToFirst();
	        
	        ArrayList<String> list;
	        //for(int visiblePosition = gridView.getFirstVisiblePosition(); visiblePosition <= gridView.getLastVisiblePosition(); visiblePosition++) {
	        	   //View view = GridView.getChildAt(visiblePosition);
	        	   // make something
	        	//}
	        for (int x = 0; x < c.getCount(); x++){
	        	// Check if this loop is being canceled
	        	if (isCancelled() == true){
	        		break;
	        	}
	        	
	        	list = new ArrayList<String>();
	        	
	        	String path = "";
	        	// Retrieves image path from database
	        	String cursorColor = c.getString(3).toString();
	        	
	        	// Select only the correct label to be added to list
	        	if (cursorColor.equals(colorIndex) || colorIndex.equals("Null") || colorIndex.equals("Choose")){
	        		path = c.getString(1).toString();
	        		list.add(path);
	        		list.add(Integer.toString(c.getInt(0)));
	        		list.add(Integer.toString(c.getInt(5)));
	        		
	        		imgUriList.add(list);
	        		bm = image.decodeBitmap(path, 80, 80);
		        	
		        	// Pass the image, to onProgressUpdate method
		        	publishProgress(new LoadedImage(bm));
		        	
	        	}
	        	// Move to the next row in database
	        	c.moveToNext();
	        	
	        }
			
			return null;
		}
		
		@Override
        public void onProgressUpdate(LoadedImage... value) {
			// Stores loaded bitmap images into an ArrayList<LoadedImage>
			for (LoadedImage image : value) {
	        	imageAdapter.add(image);
	        	imageAdapter.notifyDataSetChanged();
	        }
		}
		
		@Override
        protected void onPostExecute(String result) {
            setProgressBarIndeterminateVisibility(false);
            //db.close();
        }
    	
    }
    
    public class ListenerImageClick implements View.OnClickListener{
    	int position;
    	
    	public ListenerImageClick(int pos){
    		this.position = pos;
    	}
    	
		public void onClick(View v) {
			if (colorIndex.equals("Choose")){
				int fixedId = Integer.parseInt(imgUriList.get(position).get(2));
	
				chooseImage(imgUriList.get(position).get(0), Integer.toString(fixedId));
			}else{
				dialogImage(position);	
			}
		}
    	
    }
            
    /**
	 * Listener class for long click in an image
	 * @author Marcel
	 *
	 */
	public class ListenerImageLong implements OnLongClickListener{
		int position;
		
		public ListenerImageLong(int pos){
			this.position = pos;
		}
		
		public boolean onLongClick(View arg0) {
			dialogLabel(position);
			return false;
		}
		
	}

	/**
	 * Listener class for "Ok" button in label setting dialog
	 * Updates database in Color column
	 * @author Marcel
	 *
	 */
	public class ListenerLabelOk implements View.OnClickListener{
		int index, picPos;
		Dialog dialog;
		
		public ListenerLabelOk(int x, Dialog dialog){
			this.picPos = x;
			this.dialog = dialog;
		}
		
		public void onClick(View v) {
			// Checks which button is currently disabled, indicates the index of label user wants to set
			for (int x = 0; x < btnList.size(); x++){
				if (btnList.get(x).isEnabled() == false){
					index = x;
					break;
				}
			}
			
			//db.open();
			
			Cursor c = db.getPath();
			c.moveToPosition(picPos);
			
			// Update image's label 
			db.updatePath(c.getString(1), c.getString(2), color[index], c.getString(4), c.getInt(5));
			
			//db.close();
			
			// Close the dialog
			dialog.cancel();
		}
	}
	
	/**
	 * Listener class for buttons in the label setting dialog
	 * Enables the other 7 buttons when a button is pressed
	 * Disabled the pressed button
	 * @author Marcel
	 *
	 */
	public class ListenerLabelBtn implements View.OnClickListener{
		int pos;
		Button button;
		
		public ListenerLabelBtn(int x){
			this.pos = x;
		}
		
		public void onClick(View v) {
			for (int x = 0; x < btnList.size(); x++){
				if (x != pos){
					// Enable the other 7 buttons
					btnList.get(x).setEnabled(true);
					
				}else{
					
					// Disable the pressed button
					btnList.get(x).setEnabled(false);
				}
			}
		}
		
	}
	
	/**
	 * Pops up a label setting dialog, if a long-click action is triggered towards an image
	 * @param pos - position of image clicked
	 */
    public void dialogLabel(int pos){
		final Dialog dialog = new Dialog(this);
		
		dialog.setContentView(R.layout.labeldialog);	// Set dialog's view
		dialog.setTitle("Label");	// Set dialog's title
		
		//db.open();
		
		Cursor c = db.getLabel();
		Cursor curPath = db.getPath();
		
		// Go to image's row in database
		curPath.moveToPosition(pos);
		
		// Retrieve's current image's label
		String label = curPath.getString(3).toString();
		
		// Checks the label's index
		int curLabelIndex = 0;
		for (int x = 0; x < btnColor.length; x++){
			if (label.equals(color[x])){
				curLabelIndex = x;
			}
		}
		
		// Defines all the buttons
		for(int x = 0; x < btnColor.length; x++){
			btn = new Button(this);
			btn = (Button) dialog.findViewById(btnColor[x]);
			
			// Adds the button to the arraylist, to be able to be called again later on
			btnList.add(btn);
			
			// Sets on click listener 
			btn.setOnClickListener(new ListenerLabelBtn(x));
			
			// Disabled the button that is labeled with
			// If current label is red, disable red label button
			if (x == curLabelIndex){
				btn.setEnabled(false);
			}
			
			// There are only 7 colors in the database, but here we add 1 more, to un-labeled image called "Neutral" button
			if (x < btnColor.length - 1){
				btn.setText(c.getString(1));
				c.moveToNext();	
			}else{
				btn.setText("Neutral");
			}
		}
		
		//db.close();
		
		Button btnOk = (Button) dialog.findViewById(R.id.dialogLabelOk);
		btnOk.setOnClickListener(new ListenerLabelOk(pos, dialog));
						
		Button btnCancel = (Button) dialog.findViewById(R.id.dialogLabelCancel);
		btnCancel.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View v) {
				dialog.cancel();
			}
		});
	
		// If the dialog is canceled, the arraylist where we store all the buttons is cleared
		dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
			
			public void onCancel(DialogInterface dialog) {
				btnList.clear();
			}
		});
		
		dialog.show();
		
	}

    /**
     * Enlarge image in grid view album when clicked
     * @param position - position of the image clicked
     */
    private void dialogImage(int position){
    	imgDialog = new Dialog(this);
    	
    	// Request for no title dialog
    	imgDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    	
    	// Set the dialog view
    	imgDialog.setContentView(R.layout.enlargeimage);
    	
    	//initiates ViewPager (for swiping next / previous)
    	pager = (ViewPager) imgDialog.findViewById(R.id.albumPager);
    	pagerAdapter = new ImagePager();
    	pager.setAdapter(pagerAdapter);
    	pager.setCurrentItem(position);
    
    	imgDialog.setCancelable(true);
    	imgDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
			
			public void onDismiss(DialogInterface dialog) {
				bmEnlarge.recycle();
			}
		});
    	imgDialog.show();
    }
    
    public void chooseImage(String path, String id){
    	Intent result = new Intent();
    	Bundle extras = new Bundle();
    	extras.putString("path", path);
    	extras.putString("id", id);
    	result.putExtras(extras);
    	setResult(RESULT_OK, result);
    	finish();
    }
    
    public void getColorIndex(){
    	// Retrieves color index value passed from the previous class, to determines which label to show
        // This value will be hold by this class
        colorIndex = "";
        try{
        	Bundle extras = getIntent().getExtras();
        	
        	// Gets the color index string, for example "Red"
	    	colorIndex = extras.getString("color").toString();
	    	
        }catch(Exception e){
        	
        	// If the previous class didn't pass anything, then it will be assigned as "Null"
        	colorIndex = "Null";
        }
    }
    
    public void setTitle(){
    	TextView title = (TextView) findViewById(R.id.textTitleGrid);
        
        //db.open();
        
        Cursor cur = db.getLabel();
        
        if (colorIndex.equals("Choose")){
        	title.setText("Choose Image");
        	btnSetting.setVisibility(4);
        }
        else
        {
	        for (int x = 0; x < cur.getCount(); x++){
	        	if (cur.getString(2).toString().equals(colorIndex)){
	        		title.setText(cur.getString(1).toString());
	        		break;
	        	}
	        	
	        	cur.moveToNext();
	        }
        }
        //db.close();
    }
    
    @Override
    public void onDestroy(){
    	super.onDestroy();
    	
    	db.close();
    	
    	// If the page is destroyed, stop AsyncTask from running
    	LoadImages.cancel(true);
    	
    	bm = null;
    	bmEnlarge = null;
    	imgThumbs = null;
    	imgEnlarge = null;
    	photos.clear();
    	imgUriList.clear();
    	imageAdapter = null;
    	System.gc();
    }
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.albumgrid);
        db.open();
        
        setProgressBarIndeterminateVisibility(true);
        
        getColorIndex();
        
        // Load images on background process
        LoadImages.execute();
        
        gridView = (GridView) findViewById(R.id.albumGrid);
        imageAdapter = new ImageAdapter(this);
        gridView.setAdapter(imageAdapter);
          
        btnSetting = (Button) findViewById(R.id.btnGridSetting);
        btnSetting.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View v) {
				Intent i = new Intent(getApplicationContext(), AlbumCustom.class);
				
				// Pass color index value to the AlbumCustom class
				Bundle bundle = new Bundle();
				bundle.putString("color", colorIndex);
				i.putExtras(bundle);

				finish();
				
				// Terminate AsyncTask
				LoadImages.cancel(true);
				startActivity(i);	
			}
		});
        
        Button btnBack = (Button) findViewById(R.id.btnGridBack);
        btnBack.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View v) {
				finish();
				LoadImages.cancel(true);
			}
		});
        
        setTitle();
        
    }
    

}
